package com.ar4j.bench.ar4j.service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ar4j.bench.ar4j.domain.Item;
import com.ar4j.bench.ar4j.domain.Product;
import com.ar4j.bench.common.domain.IItem;
import com.ar4j.bench.common.domain.IProduct;
import com.ar4j.bench.common.domain.ProductWithItems;
import com.ar4j.bench.common.service.IProductService;

/**
 * A product service implemented using the AR4J library
 */
@Service
public class ProductAr4jService implements IProductService {
  
  @Autowired
  private Product productAdapter;
  
  @Autowired
  private Item itemAdapter;
  
  @Override
  public Long addProduct(IProduct product) {
    return ((Product) product).save().getId();
  }

  @Override
  public Long addProductWithItems(ProductWithItems product) {
    Long productId = addProduct(product.getProduct());
    for(IItem item : product.getItems()) {
      item.setProductId(productId);
      ((Item) item).save();
    }
    
    return productId;
  }

  @SuppressWarnings("unchecked")
  @Override
  public List<IProduct> findByCategoryId(Long categoryId) {
    return (List<IProduct>) ((List<?>) productAdapter.findAllByCategoryId(categoryId));
  }

  @Override
  public IProduct findById(Long id) {
    return productAdapter.findByIdentifier(id);
  }

  @SuppressWarnings("unchecked")
  @Override
  public List<ProductWithItems> findProductWithItemsByCategoryId(Long categoryId) {
    List<ProductWithItems> out = new ArrayList<ProductWithItems>();
    for(IProduct product : findByCategoryId(categoryId)) {
      ProductWithItems withItems = new ProductWithItems();
      withItems.setProduct(product);
      withItems.setItems((List<IItem>) ((List<?>) itemAdapter.findAllByProductId(product.getId())));
      out.add(withItems);
    }
    
    return out;
  }

  @SuppressWarnings("unchecked")
  @Override
  public ProductWithItems findProductWithItemsById(Long id) {
    ProductWithItems out = new ProductWithItems();
    
    IProduct product = findById(id);
    out.setProduct(product);
    out.setItems((List<IItem>) ((List<?>) itemAdapter.findAllByProductId(product.getId())));
    
    return out;
  }

  @Override
  public void removeById(Long id) {
    productAdapter.deleteByIdentifier(id);    
  }

  @Override
  public void removeProductWithItemsById(Long id) {
    itemAdapter.deleteByProductId(id);
    productAdapter.deleteByIdentifier(id);
  }

  @Override
  public void updateProduct(IProduct product) {
    Product theProduct = (Product) product;
    theProduct.save();
  }

  @Override
  public void updateProductWithItems(ProductWithItems product) {
    updateProduct(product.getProduct());
    
    Set<Long> fromDb = new HashSet<Long>();
    for(Item item : itemAdapter.findAllByProductId(product.getProduct().getId())) {
      fromDb.add(item.getId());
    }
    
    for(IItem item : product.getItems()) {
      fromDb.remove(item.getId());
      ((Item) item).save();
    }
    
    itemAdapter.deleteByIdentifier(fromDb);
  }

}
